<script lang="ts" setup>
// 组件
import { ElMessage } from "element-plus";

// Store
import { useCanvasStoreHook } from "@/stores/modules/canvas";
import { useSelectGraphStoreHook } from "@/stores/modules/selectGraph";
import { useKBStoreHook } from "@/stores/modules/KB";
import { operateOption } from "./index";
import { uniqueFunc } from "@/utils/index";
import { isNeedStop } from "@/views/associationAnalysis/canvas/components/canvasG6/common/menuEvent";
import useCanvas from "@/hooks/canvas/useCanvas";
import { graph } from "@/views/associationAnalysis/canvas/components/canvasG6/common/index";

// 接口
import {
  fetchListEntityTypeRel,
  fetchExpansion,
} from "@/api/associationAnalysis";

// 弹窗Props
export interface Props {
  visible: boolean;
  id?: string;
}

// 弹窗展示与隐藏
const props = withDefaults(defineProps<Props>(), {
  visible: false,
  id: "",
});

interface Emit {
  (e: "update:visible", visible: boolean): void;
}

const emit = defineEmits<Emit>();

const show = computed({
  get() {
    return props.visible;
  },
  set(visible: boolean) {
    emit("update:visible", visible);
  },
});

// 当前步骤
const step = ref(1);

// 获取当前画布中的点
const useCanvasStore = useCanvasStoreHook();
const useSelectGraphStore = useSelectGraphStoreHook();
const selectCanvas = useSelectGraphStore.getSelectCanvas();
let dataNodes = useCanvasStore.getCanvasByData().nodes;
let nodes = [];

if (selectCanvas && selectCanvas.nodes.length) {
  nodes = JSON.parse(JSON.stringify(dataNodes)).map((item) => {
    item.check = false;
    selectCanvas.nodes.forEach((ele) => {
      if (item.id === ele.id) {
        item.check = true;
        nextTick(() => {
          handleCheckNodesChange(item);
        });
      }
    });
    return item;
  });
} else {
  nodes = JSON.parse(JSON.stringify(dataNodes)).map((item) => {
    item.check = false;
    return item;
  });
}

const canvas = ref(nodes);

// 获取所有tags
const useKBStore = useKBStoreHook();
const KBTags = useKBStore.tags;
const useTags = JSON.parse(JSON.stringify(KBTags))
  .filter(
    (item) => canvas.value.findIndex((ele) => ele.tageName === item.code) > -1
  )
  .map((item) => {
    item.checkAll = false;
    item.indeterminate = false;
    return item;
  });
const tags = ref(useTags);

const checkAll = ref(false); // 全选
const isIndeterminate = ref(false); // 半选
const checkNodes = ref([]); // 选中的对象集合

// 全选选中时的事件
const handleCheckAllChange = (value) => {
  checkNodes.value = [];
  canvas.value.forEach((item) => {
    item.check = value;
    if (value) {
      checkNodes.value.push(item);
    }
  });
  tags.value.forEach((item) => {
    item.checkAll = value;
    item.indeterminate = false;
  });
  isIndeterminate.value = false;
  if (!value) {
    checkNodes.value = [];
  }
};

// 点选中时的事件
const handleCheckNodesChange = (item) => {
  if (item.check) {
    checkNodes.value.push(item);
  } else {
    checkNodes.value = checkNodes.value.filter((ele) => ele.id !== item.id);
  }
  tags.value.forEach((k) => {
    const { code } = k;
    const allNodes = canvas.value.filter((ele) => ele.tageName === code);
    const allCheckNodes = checkNodes.value.filter(
      (ele) => ele.tageName === code
    );
    const checkedCount = allCheckNodes.length;
    const totalCount = allNodes.length;
    const isAllChecked = checkedCount === totalCount;
    const isIndeterminate = checkedCount > 0 && checkedCount < totalCount;
    k.checkAll = isAllChecked;
    k.indeterminate = isIndeterminate;
  });

  checkAll.value = tags.value.every((item) => item.checkAll);
  isIndeterminate.value =
    tags.value.some((item) => item.checkAll) && !checkAll.value;
};

// tags选中时的事件
const handleTagsChange = (item) => {
  item.indeterminate = false;
  canvas.value.forEach((ele) => {
    if (ele.tageName === item.code) {
      ele.check = item.checkAll;
      if (item.checkAll) {
        checkNodes.value.push(ele);
      } else {
        checkNodes.value = checkNodes.value.filter((k) => k.id !== ele.id);
      }
    }
  });
  checkAll.value = tags.value.every((item) => item.checkAll);
  isIndeterminate.value =
    tags.value.some((item) => item.checkAll) && !checkAll.value;
};

// 边的集合
const edgeType = ref([]);

// 下一步按钮事件
const handleNext = async () => {
  if (checkNodes.value.length === 0) {
    ElMessage({
      message: "请至少选中一个",
      type: "warning",
    });
    return;
  }
  let filterTags = tags.value
    .filter((item) => item.checkAll || item.indeterminate)
    .map((item) => item.code);
  let data = {
    entityTypeCodeList: filterTags,
    relationDirection: 0,
  };
  try {
    let res = await fetchListEntityTypeRel(data);
    edgeType.value = res.data.map((item) => {
      let set = {};
      item.propertyDTOList.forEach((ele) => {
        set[ele.code + "Option"] =
          operateOption[ele.dataType] ?? operateOption.string;
      });
      return {
        ...item,
        check: false,
        props: [],
        ...set,
      };
    });
    if (edgeType.value.length) {
      step.value = 2;
    } else {
      ElMessage.error("该节点暂无类型");
    }
  } catch (error) {
    // ElMessage.error(error);
  }
};

const defaultProps = {
  children: "children",
  label: "name",
};
const edgeTypeIndex = ref(0);

const handleEdgeTypeChange = (node, TreeNode, e) => {
  let index = edgeType.value.findIndex((item) => item.id === node.id);
  edgeTypeIndex.value = index;
};

const handleAddProps = () => {
  edgeType.value[edgeTypeIndex.value].props.push({
    key: "",
    operate: "",
    value: "",
    type: "",
  });
};

/** 改变选择类型将当前类型传给后端 */
const changeType = (item, typeArr) => {
  console.log(item, typeArr);
  item.type = typeArr.find((it) => it.code == item.key).dataType;
  item.value = "";
};

const handleDelProps = (index) => {
  edgeType.value[edgeTypeIndex.value].props.splice(index, 1);
};

const handleCheckChange = (data, checked: boolean, indeterminate: boolean) => {
  data.check = checked;
};

const analysisBtnDisabled = computed(() => {
  return edgeType.value.every((item) => !item.check);
});

const handleAnalysis = async () => {
  let data = edgeType.value
    .filter((item) => item.check)
    .map((item) => {
      return {
        direction: "BOTH",
        name: item.code,
        props: item.props,
      };
    });

  //  校验筛选条件是否输入完整，不完整不让请求接口
  for (let i = 0; i < data.length; i++) {
    for (let j = 0; j < data[i].props.length; j++) {
      if (
        !data[i].props[j].key ||
        !data[i].props[j].operate ||
        (!data[i].props[j].value && data[i].props[j].value != 0)
      )
        return ElMessage("请将筛选条件填写完整");
    }
  }
  let vertexes = checkNodes.value.map((item) => {
    return {
      tags: item.tags.map((item) => item.name),
      vid: item.vid,
    };
  });
  let params = {
    edgeType: data,
    step: 1,
    vertexes,
  };
  if (!vertexes.length) return ElMessage("暂无可拓展的节点");
  let res = await fetchExpansion(params);

  const data1 = {
    nodes: [],
    edges: [],
  };
  data1.edges = res.relations.map((item, index) => {
    return {
      ...item,
      id: `${item.srcID}_${item.dstID}_${item.code}_${item.rank}`,
      label: useKBStore.getTagEdgesByName(item.edgeName),
      target: item.dstID, // 目标点 id
      source: item.srcID, // 起始点 id
    };
  });
  data1.nodes = res.vertexes.map((item, index) => {
    return {
      ...item,
      id: item.vid,
      label: getSysName(item.tags),
    };
  });
  // data1.nodes = data1.nodes.concat(useCanvasStore.getCanvasByData().nodes);
  data1.edges = uniqueFunc(
    // 去除id相同的边
    data1.edges.concat(useCanvasStore.getCanvasByData().edges)
  );
  data1.nodes = useCanvas(data1.nodes, useCanvasStore.getCanvasByData()).nodes;

  isNeedStop.value = true; // 阻止画布重新渲染，防止后退失效
  graph.changeData(data1); // 更新画布，添加撤销操作栈
  useCanvasStore.setCanvas(JSON.parse(JSON.stringify(data1)));

  useSelectGraphStore.setSelectCanvas(null);

  show.value = false;
};

// 搜索结果获取sysName值
const getSysName = (tags) => {
  let sysName = "";
  tags.forEach((item) => {
    if (item.properties.sys_name) {
      sysName = item.properties.sys_name;
    }
  });
  return sysName;
};
</script>

<template>
  <div class="relationDialog">
    <el-dialog v-model="show" title="关系拓展" width="770px">
      <div class="main">
        <header :class="step === 1 ? 'start' : 'end'" class="main-header">
          <span :class="step === 1 ? 'text-white' : ''">起始对象</span>
          <span :class="step === 2 ? 'text-white' : ''">关系类型</span>
        </header>
        <div class="select-main">
          <p>
            当前最多选择1000个对象，当前已选
            <span class="text-[#2B1DFF]">{{ checkNodes.length }}</span>
            个。
          </p>
          <div class="select">
            <div v-if="step === 1" class="select-left">
              <el-checkbox
                v-model="checkAll"
                :indeterminate="isIndeterminate"
                @change="handleCheckAllChange"
              >
                全部
              </el-checkbox>
              <div class="pl-4 flex flex-col">
                <el-checkbox
                  v-for="item in tags"
                  :key="item.id"
                  v-model="item.checkAll"
                  :indeterminate="item.indeterminate"
                  :label="item"
                  @change="handleTagsChange(item)"
                >
                  {{ item.name }}
                </el-checkbox>
              </div>
            </div>
            <div v-else class="select-left">
              <el-tree
                :data="edgeType"
                :props="defaultProps"
                show-checkbox
                @node-click="handleEdgeTypeChange"
                @check-change="handleCheckChange"
              />
            </div>
            <div v-if="step === 1" class="select-right">
              <el-checkbox
                v-for="item in canvas"
                :key="item.id"
                v-model="item.check"
                :label="item"
                class="w-[210px] checkbox"
                :title="item.label"
                @change="handleCheckNodesChange(item)"
              >
                {{ item.label }}
              </el-checkbox>
            </div>
            <div v-else class="select-right">
              <div>
                <span>筛选条件</span>
                <i
                  class="iconfont icon_input_add1 text-[#99A3B8] ml-[8px]"
                  @click="handleAddProps"
                ></i>
              </div>
              <div
                v-for="(item, index) in edgeType[edgeTypeIndex].props"
                :key="index"
                class="flex items-center justify-between mt-[16px]"
              >
                <el-select
                  v-model="item.key"
                  class="mr-[16px]"
                  placeholder="请选择"
                  style="width: 150px"
                  @change="
                    changeType(item, edgeType[edgeTypeIndex].propertyDTOList)
                  "
                >
                  <el-option
                    v-for="ele in edgeType[edgeTypeIndex].propertyDTOList"
                    :key="ele.code"
                    :label="ele.name"
                    :value="ele.code"
                  />
                </el-select>
                <el-select
                  v-model="item.operate"
                  class="mr-[16px]"
                  placeholder="运算符"
                  style="width: 150px"
                >
                  <el-option
                    v-for="ele in edgeType[edgeTypeIndex][item.key + 'Option']"
                    :key="ele.value"
                    :label="ele.label"
                    :value="ele.value"
                  />
                </el-select>
                <!-- 整数 -->
                <el-input-number
                  v-if="item.type == 'int'"
                  v-model="item.value"
                  class="mr-[16px]"
                  :precision="0"
                />
                <!-- 浮点数 -->
                <el-input-number
                  v-else-if="
                    item.type == 'float' ||
                    item.type == 'double' ||
                    item.type == 'number'
                  "
                  v-model="item.value"
                  class="mr-[16px]"
                  :precision="2"
                />
                <!-- 时间日期 -->
                <el-date-picker
                  v-else-if="item.type == 'datetime'"
                  v-model="item.value"
                  class="mr-[16px]"
                  type="datetime"
                  placeholder="请选择"
                  format="YYYY-MM-DD hh:mm:ss"
                  value-format="YYYY-MM-DD hh:mm:ss"
                />
                <!-- 日期 -->
                <el-date-picker
                  v-else-if="item.type == 'date'"
                  v-model="item.value"
                  class="mr-[16px]"
                  format="YYYY-MM-DD"
                  value-format="YYYY-MM-DD"
                  type="date"
                  placeholder="请选择"
                />
                <!-- 时间 -->
                <el-time-picker
                  v-else-if="item.type == 'time'"
                  v-model="item.value"
                  class="mr-[16px]"
                  placeholder="请选择"
                />
                <!-- 其他 -->
                <el-input
                  v-else
                  v-model="item.value"
                  class="mr-[16px]"
                  placeholder="值"
                  style="width: 150px"
                />
                <i
                  class="iconfont icon_delete_fill text-[#7F8A9B]"
                  @click="handleDelProps(index)"
                ></i>
              </div>
            </div>
          </div>
        </div>

        <div class="footer">
          <el-button @click="show = false">取消</el-button>
          <el-button v-if="step === 2" @click="step = 1">上一步</el-button>
          <el-button v-if="step === 1" type="primary" @click="handleNext">
            下一步
          </el-button>
          <el-button
            v-else
            :disabled="analysisBtnDisabled"
            type="primary"
            @click="handleAnalysis"
          >
            立即分析
          </el-button>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<style lang="scss" scoped>
.relationDialog {
  :deep(.el-dialog__body) {
    border-top: 1px solid #edeff4;
  }

  .main {
    width: 100%;

    &-header {
      display: flex;
      align-items: center;
      justify-content: center;
      width: 100%;
      height: 40px;
      font-family: PingFangSC-Regular, "PingFang SC";
      font-size: 16px;
      font-weight: 400;
      line-height: 22px;
      color: #222;
      background-color: #f7f8fa;

      > span {
        flex: 1;
        text-align: center;
      }
    }

    .start {
      background-image: url("@/assets/images/associationAnalysis/start.png");
      background-repeat: no-repeat;
      background-size: 50% 100%;
    }

    .end {
      background-image: url("@/assets/images/associationAnalysis/end.png");
      background-repeat: no-repeat;
      background-position: right;
      background-size: 50% 100%;
    }

    .select-main {
      width: 100%;
      margin-top: 24px;

      > p {
        margin-bottom: 16px;
        font-family: PingFangSC-Regular, "PingFang SC";
        font-size: 12px;
        font-weight: 400;
        line-height: 20px;
        color: #222;
      }

      .select {
        display: flex;
        width: 100%;

        &-left {
          display: flex;
          flex-direction: column;
          width: 200px;
          height: 320px;
          overflow: hidden;
          overflow-y: auto;
          border-right: 1px solid #edeff4;
        }

        &-right {
          box-sizing: border-box;
          flex: 1;
          height: 320px;
          padding-right: 16px;
          padding-left: 16px;
          overflow: hidden;
          overflow-y: auto;
        }

        .checkbox {
          ::v-deep .el-checkbox__label {
            overflow: hidden;
            text-overflow: ellipsis;
            white-space: nowrap;
          }
        }
      }
    }

    .footer {
      display: flex;
      justify-content: flex-end;
      width: 100%;
      margin-top: 24px;
    }
  }
}
</style>
